/*
 * main.c
 *
 *  Created on: 2018-8-19
 *      Author: Administrator
 */

#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include <xtensa/xtruntime.h>
#include <xtensa/hal.h>

#include "xa_type_def.h"

#include "ipc.h"
#include "user_def.h"
#include "plf.h"
#include "uart.h"
#include "flash.h"
#include "qspi.h"
#include "audio_algorithm.h"
#include "os_timer.h"
#include "co_mem.h"
#include "lvgl.h"
#include "lv_port_disp.h"
#include "lv_port_indev.h"
#include "GUI_Touch.h"
#include "GUI_core.h"
#include "Time.h"

extern Time_t my_Time;

extern Touch_Status_t Touch_Status;
extern Touch_Stack_t  Touch_Stack;  //全局触摸栈



#define FLASH_ID_BY_USER            0x174068
#define FLASH_ID_DOSI_64M			0x1732f8
#define FLASH_ID_BOYA_128M			0x184068
#define FLASH_ID_PUYA_128M			0x186085
#define FLASH_ID_PUYA_64M			0x174068
#define FLASH_ID_PUYA_32M			0x166085
#define FLASH_ID_PUYA_16M			0x156085
#define FLASH_ID_PUYA_4M            0x136085
#define FLASH_ID_XTX_128M			0x18400B
#define FLASH_ID_UNKNOWN_128M       0x184068
#define FLASH_ID_NORMEM_64M         0x172252

void app_ipc_rx_set_user_handler(void *arg);
void app_register_default_task_handler(void *arg);

void init_memory(void);
void app_entry(void);

void sbc_encoder_recv_frame_req(void *);

void mp3_decoder_init(void *arg);
void mp3_decoder_recv_frame(pWORD8 buffer, UWORD32 length);
void mp3_decoder_do_decoder_handler(void *);

void audio_init(void *msg);
void audio_algorithm_release(void *msg);
extern void audio_algorithm_ipc_rx_handler(struct task_msg_t *msg);
extern void audio_algorithm_ipc_tx_handler(struct task_msg_t *msg);
extern void app_at_cmd_recv_handler(struct task_msg_t *msg);
extern void os_timer_trigger_handler(struct task_msg_t *msg);

__attribute__((section("entry_point_section"))) const uint32_t entry_point[] = {
    (uint32_t)app_entry,
};

uint8_t btn_sat[2] = {0,0};
uint8_t btn_num = 0xff;

extern struct sbc_info_t sbc_info;

void set_btn(uint8_t btn_num, bool sat)
{
    if(btn_num == 0x01) {
        btn_sat[0] = sat;
    }
    else if(btn_num == 0x02) {
        btn_sat[1] = sat;
    }
}

uint8_t get_btn(uint8_t num)
{
    uint8_t ret = 0;

    if(num == 0) {
        ret = btn_sat[0];
        return ret;
    }
    else if(num == 1) {
        ret = btn_sat[1];
        return ret;
    }
}

void test_flash_read_write(struct task_msg_t *msg)
{
#define TEST_FLASH_READ_WRITE_LENGTH        16
    uint8_t test_data[TEST_FLASH_READ_WRITE_LENGTH];
    uint8_t status[2];
    static uint8_t *ptr = (uint8_t *)0x00184000;
    static uint32_t start_flash_addr = 512*1024;

    printf("TEST flash: dest = %08x, src = %08x\r\n", start_flash_addr, ptr);
    memcpy(test_data, (void *)(start_flash_addr+QSPI1_DAC_ADDRESS), TEST_FLASH_READ_WRITE_LENGTH);
	printf("TEST BEFORE: ");
	for(uint32_t i=0; i<TEST_FLASH_READ_WRITE_LENGTH; i++) {
		printf("%02x ", test_data[i]);
	}
	printf("\r\n");

    qspi_flash_erase(start_flash_addr, 0x1000);
    qspi_flash_write(start_flash_addr, TEST_FLASH_READ_WRITE_LENGTH, (void *)ptr);

    memcpy(test_data, (void *)(start_flash_addr+QSPI1_DAC_ADDRESS), TEST_FLASH_READ_WRITE_LENGTH);
    printf("TEST AFTER: \r\nREAD:  ");
    for(uint32_t i=0; i<TEST_FLASH_READ_WRITE_LENGTH; i++) {
    	printf("%02x ", test_data[i]);
        }
    printf("\r\n");
    printf("CHECK: ");
	for(uint32_t i=0; i<TEST_FLASH_READ_WRITE_LENGTH; i++) {
		printf("%02x ", *ptr++);
    }
	printf("\r\n");

	start_flash_addr += 4096;
	if(start_flash_addr >= 1024*1024) {
		start_flash_addr = 512*1024;
	}
	if((uint32_t)ptr >= 0x00186000) {
		ptr = (uint8_t *)0x00184000;
	}
}

struct os_timer_t test_flash_rw_timer;
void test_flash_rw_timer_function(void *arg)
{
	test_flash_read_write(NULL);
}

struct os_timer_t test_st7796_timer;
struct os_timer_t test_st7789_timer;

struct os_timer_t My_time_timer;
struct os_timer_t GUI_timer;
struct os_timer_t Touch_timer;

void GUI_timer_function(void *arg)
{
	//printf("%s\r\n",__FUNCTION__);
	GUI_Refresh_Handler();//GUI刷新函数
}


void Touch_timer_function(void *arg)
{
	GUI_Touch_Handler();//GUI触摸函数
}



void My_time_timer_function(void *arg)
{
	//GUI_Touch_Handler();//GUI触摸函数

	printf(" %s  minute=%d,seconds=%d\r\n",__FUNCTION__,my_Time.minute,my_Time.seconds);
	my_Time.seconds++;

	if(my_Time.seconds>=60)
	{
		my_Time.seconds=0;
		my_Time.minute++;

		if(my_Time.minute>=60)
		{
		    my_Time.minute=0;
			my_Time.hour++;
		}
	}





}



void test_st7789V_timer_init(void *arg)
{
	st7796h_init();//��ʼ����Ļ

}
#if 1
extern const unsigned char gImage_bg3[115200];
#endif


#if 0
lv_obj_t * img2=NULL;
lv_obj_t * img3=NULL;
unsigned int angle=0;
void rolate_Hander(lv_task_t * task)
{
  angle+=45;

	//lv_img_set_angle(img2, angle);
  lv_img_set_angle(img3, angle);
  printf("rolate_Hander\r\n");
}

#else

#if 1


LV_IMG_DECLARE(bg1);   //����ͼƬ��Դ
LV_IMG_DECLARE(bg2);   //����ͼƬ��Դ
LV_IMG_DECLARE(bg3);   //����ͼƬ��Դ
LV_IMG_DECLARE(bg4);   //����ͼƬ��Դ


lv_obj_t * img1;
lv_obj_t * img2;
lv_obj_t * img3;
lv_obj_t * img4;




lv_obj_t * img11;
lv_obj_t * img22;
lv_obj_t * img33;
lv_obj_t * img44;



lv_obj_t * slider;//ȫ�ֵ��������ƶ���




unsigned int angle=0;
unsigned int angle1=0;
unsigned int count=0;

lv_obj_t * table_view_main;//����ȫ�ֵĽ������


void rolate_Hander()
{
  angle+=20;

//lv_img_set_zoom(img1,angle);

	lv_img_set_angle(img2, angle);

	lv_img_set_angle(img22, angle);

		if(angle>=3600)

		{
		  angle=0;
		  angle1+=20;
		  lv_img_set_angle(img3, angle1);
		  lv_img_set_angle(img33, angle1);

		}


}


void table_change(lv_task_t * task)
{

	count++;
	if(count==1)
	{
		lv_tabview_set_anim_time(table_view_main,2000);
	    lv_tabview_set_tab_act(table_view_main,count,LV_ANIM_ON);


	}else if(count==2)
	{
		lv_tabview_set_anim_time(table_view_main,2000);
	    lv_tabview_set_tab_act(table_view_main,count,LV_ANIM_ON);



	}else  if(count==3)
	{
		count=0;
		lv_tabview_set_anim_time(table_view_main,2000);
	    lv_tabview_set_tab_act(table_view_main,count,LV_ANIM_ON);




	}



}


static void slider_event_cb(lv_obj_t * slider, lv_event_t event)
{
    int16_t barvalue = 0;

    if(event == LV_EVENT_VALUE_CHANGED) {
        static char buf[4]; /* max 3 bytes for number plus 1 null terminating byte */

       barvalue =  lv_slider_get_value(slider);
       printf("barvlue is %d\r\n",barvalue);
        //snprintf(buf, 4, "%u", lv_slider_get_value(slider));
        //lv_label_set_text(slider_label, buf);
    }
}

void table_Init()
{


	table_view_main=lv_tabview_create(lv_scr_act(), NULL);//����ҳ�����
	lv_tabview_set_btns_pos(table_view_main,LV_TABVIEW_TAB_POS_NONE);//ȡ����ʾ��ť





    lv_obj_t *tab1 = lv_tabview_add_tab(table_view_main, "Tab 1");
    lv_obj_t *tab2 = lv_tabview_add_tab(table_view_main, "Tab 2");
    lv_obj_t *tab3 = lv_tabview_add_tab(table_view_main, "Tab 3");

	lv_tabview_set_tab_act(table_view_main,0,LV_ANIM_OFF);
	//lv_tabview_set_tab_act(table_view_main,1,LV_ANIM_OFF);
	//lv_tabview_set_tab_act(table_view_main,2,LV_ANIM_OFF);


#if 0
        /*Create a slider*/
       slider = lv_slider_create(tab1, NULL);
       lv_obj_set_pos(slider, 180, 20);//����λ��
       lv_obj_set_size(slider, 10, 150);//���ô�С
       //lv_obj_set_hidden(slider, true);
       lv_slider_set_range(slider,0,50);

       lv_obj_set_event_cb(slider, slider_event_cb);

#endif





   // lv_task_create(table_change, 5000, LV_TASK_PRIO_HIGHEST, NULL);

   // lv_page_set_scrlbar_mode(page[i].parent, LV_SCROLLBAR_MODE_OFF);//ȡ����ʾ������
/*  lv_page_set_scrlbar_mode(tab1, LV_SCROLLBAR_MODE_OFF);//ȡ����ʾ������
    lv_page_set_scrlbar_mode(tab2, LV_SCROLLBAR_MODE_OFF);//ȡ����ʾ������
    lv_page_set_scrlbar_mode(tab3, LV_SCROLLBAR_MODE_OFF);//ȡ����ʾ������
*/






#if 1
	     LV_IMG_DECLARE(main_back);//����ͼƬ��Դ
		 LV_IMG_DECLARE(minute);   //����ͼƬ��Դ
		 LV_IMG_DECLARE(hour);   //����ͼƬ��Դ
		 LV_IMG_DECLARE(second);   //����ͼƬ��Դ


#if 1
		lv_obj_t * img1 = lv_img_create(tab1, NULL);
	    lv_img_set_src(img1, &bg1);
	    lv_obj_align(img1, NULL, LV_ALIGN_CENTER, 0, 0);




		img2 = lv_img_create(img1, NULL);
	    lv_img_set_src(img2, &second);
	    lv_obj_set_pos(img2, 120, 0);



		img3 = lv_img_create(img1, NULL);
	    lv_img_set_src(img3, &minute);
	    lv_obj_set_pos(img3, 120, 0);


	    img4 =lv_img_create(img1, NULL);
	    lv_img_set_src(img4, &hour);
	    lv_obj_set_pos(img4, 120-10, 28);



		lv_img_set_pivot(img2, 0, 120);//������ת���
		lv_img_set_pivot(img3, 0, 120);//������ת���



#endif
		lv_obj_t * img11 = lv_img_create(tab2, NULL);
	    lv_img_set_src(img11, &bg3);
	    lv_obj_align(img11, NULL, LV_ALIGN_CENTER, 0, 0);





		img22 = lv_img_create(img11, NULL);
	    lv_img_set_src(img22, &second);
	    lv_obj_set_pos(img22, 120, 0);



		img33 = lv_img_create(img11, NULL);
	    lv_img_set_src(img33, &minute);
	    lv_obj_set_pos(img33, 120, 0);


	    img44 =lv_img_create(img11, NULL);
	    lv_img_set_src(img44, &hour);
	    lv_obj_set_pos(img44, 120-10, 28);



		lv_img_set_pivot(img2, 0, 120);//������ת���
		lv_img_set_pivot(img3, 0, 120);//������ת���



		lv_img_set_pivot(img22, 0, 120);//������ת���
		lv_img_set_pivot(img33, 0, 120);//������ת���




		lv_task_create(rolate_Hander, 10, LV_TASK_PRIO_HIGHEST, NULL);
		//lv_task_create(task4_cb, 5000, LV_TASK_PRIO_MID, NULL);



		//lv_task_create(task4_cb, 5000, LV_TASK_PRIO_MID, NULL);
		printf("IMG Init\r\n");

#endif








}





void task4_cb(lv_task_t * task)//�����  5000msʱ��ˢ������   ����ˢ��
{

	 count++;
			  if(count==1)
			  {
				  printf("set src count=%d\r\n",count);
				  lv_img_set_src(img1, &bg1);

			  }else  if(count==2)
			  {

				  lv_img_set_src(img1, &bg2);
			  }else  if(count==3)
			  {
				  lv_img_set_src(img1, &bg3);

			  }else  if(count>=4)
			  {
				  lv_img_set_src(img1, &bg4);
				  count=0;
			  }





	/*
	i++;
	if(i==1)lv_img_set_src(img_back, "F:/BackGround/you1.bin");
	if(i==2)lv_img_set_src(img_back, "F:/BackGround/you2.bin");
	if(i==3)lv_img_set_src(img_back, "F:/BackGround/you3.bin");
	if(i>=4)
	{

		i=0;
	}
	*/


}





#endif

#endif



struct os_timer_t test_lvgl_timer;


struct os_timer_t lvgl_tick_timer;
void lvgl_tick_function(void *arg)
{
	  lv_tick_inc(5);//lvgl 1ms ����
	 // printf("lvgl tick running\r\n");
}



void test_lvgl_timer_function(void *arg)
{
	static uint8_t rm69330_test_counter = 1;
#if 0
	if(rm69330_test_counter == 0) {
		//rm69330_init();

		lv_init();
		printf("lv_init\r\n");
		co_delay_100us(20);

		lv_port_disp_init();
		printf("lv_port_disp_init\r\n");

		printf("LV Success Init\r\n");

		 LV_IMG_DECLARE(main_back);//����ͼƬ��Դ
		 LV_IMG_DECLARE(minute);   //����ͼƬ��Դ


		lv_obj_t * img1 = lv_img_create(lv_scr_act(), NULL);
	    lv_img_set_src(img1, &main_back);
	    lv_obj_align(img1, NULL, LV_ALIGN_CENTER, 0, 0);


	    img2 = lv_img_create(img1, NULL);
	    lv_img_set_src(img2, &minute);
	    lv_obj_align(img2, NULL, LV_ALIGN_CENTER, 0, 0);


		img3 = lv_img_create(img1, NULL);
	    lv_img_set_src(img3, &minute);
	    lv_obj_align(img3, NULL, LV_ALIGN_CENTER, 0, 0);




		lv_img_set_pivot(img2, 120, 120);//������ת���
		lv_img_set_pivot(img3, 120, 120);//������ת���
		lv_task_create(rolate_Hander, 10, LV_TASK_PRIO_HIGHEST, NULL);

		printf("IMG Init\r\n");
		//lv_port_indev_init();
		//lv_test_theme_1(lv_theme_night_init(210, NULL));
	}

#endif

	if((rm69330_test_counter % 10) == 0){
		lv_task_handler();
	    //printf("lv_task_handler\r\n");
	}

    rm69330_test_counter++;
    if(rm69330_test_counter > 250) {
    	rm69330_test_counter = 1;
    }
}




void test_st7796_timer_function(void *arg)
{
	static uint8_t st7796_test_counter = 1;
	printf("test_timer_function\r\n");
	if(st7796_test_counter == 0) {
		st7796h_init();
	}


	 if(st7796_test_counter == 1) {
	//st7796h_draw_solid_rect(0,0,240,240,0xF800);
#if 1
    #define TEST_FLASH_READ_LENGTH          115200
    uint8_t buffer[115200];
    memcpy(buffer, gImage_bg3, 115200);

	st7796h_draw(0, 0, 240, 240, buffer);
#endif
	 //vPortFree(buffer);
	}
#if 1
	else if(st7796_test_counter == 2) {
	st7796h_draw_solid_rect(0,0,240,240,0xFFFF);

	//st7796h_draw(0, 0, 240, 240, gImage_bg2);
	}
	else if(st7796_test_counter == 3) {
    st7796h_draw_solid_rect(0,0,240,240,0x0000);
    //st7796h_draw(0, 0, 240, 240, gImage_bg3);
	}else  if(st7796_test_counter== 4 )
	{
	 //st7796h_draw_solid_rect(0,0,240,240,0xFFFF);
	//st7796h_draw(0, 0, 240, 240, gImage_bg4);
	}else if(st7796_test_counter== 5)
	{
		//st7796h_draw_solid_rect(0,0,240,240,0x0000);
		//st7796h_draw(0, 0, 240, 240, gImage_1);

	}

#endif

	st7796_test_counter++;
	if(st7796_test_counter >= 6) {
		st7796_test_counter = 1;

		//os_timer_stop(&test_st7796_timer);//ֹͣ��ʱ��
	}

}

struct os_timer_t test_rm69330_timer;
void test_rm69330_timer_function(void *arg)
{
	static uint8_t rm69330_test_counter = 0;

	if(rm69330_test_counter == 0) {
		rm69330_init();

		lv_init();
		co_delay_100us(20);
		lv_port_disp_init();
		//lv_port_indev_init();
		//lv_test_theme_1(lv_theme_night_init(210, NULL));
	}

	if((rm69330_test_counter % 10) == 0){
		lv_task_handler();
	}

    rm69330_test_counter++;
    if(rm69330_test_counter > 250) {
    	rm69330_test_counter = 1;
    }
}

struct os_timer_t test_rm69330_button_timer;
void test_rm69330_button_timer_function(void *arg)
{
	static uint8_t stage = 0;

	if(stage == 1) {
		set_btn(1, 1);
	}
	else if(stage == 2) {
		set_btn(1, 0);
	}
	else if(stage == 3) {
		set_btn(2, 1);
	}
	else if(stage == 4) {
		set_btn(2, 0);
	}

	stage++;
	if(stage > 4) {
		stage = 1;
	}
}
extern const unsigned char gImage_rtkpic[];
extern const unsigned char gImage_rtkpic1[];
struct os_timer_t test_gc9c01_timer;
void test_gc9c01_timer_function(void *arg)
{
	static uint8_t gc9c01_test_counter = 0;

	if(gc9c01_test_counter == 0) {
		lcd_gc9c01_init();
#if 0
		//lcd_gc9c01_set_windows(0, 0, 121, 121);
		lcd_gc9c01_set_windows(186, 202, 186+122-1, 202+122-1);
		lcd_gc9c01_display(gImage_rtkpic, 29768);
#else
		_xtos_interrupt_disable(XCHAL_TIMER1);
		lcd_gc9c01_set_windows(0, 0, 359, 359);
		lcd_gc9c01_display(gImage_rtkpic1, 259200);
#endif
		//while(1);

		lv_init();
		co_delay_100us(20);
		lv_port_disp_init();
		lv_port_indev_init();
		lv_test_theme_1(lv_theme_night_init(210, NULL));
	}

	if((gc9c01_test_counter % 2) == 0){
		lv_task_handler();
	}

	gc9c01_test_counter++;
    if(gc9c01_test_counter > 250) {
    	gc9c01_test_counter = 1;
    }
}

struct os_timer_t test_gc9c01_button_timer;
void test_gc9c01_button_timer_function(void *arg)
{
	static uint8_t stage = 0;

	if(stage == 1) {
		set_btn(1, 1);
	}
	else if(stage == 2) {
		set_btn(1, 0);
	}
	else if(stage == 3) {
		set_btn(2, 1);
	}
	else if(stage == 4) {
		set_btn(2, 0);
	}

	stage++;
	if(stage > 4) {
		stage = 1;
	}
}
uint8_t MCU_Data[50]={0};
static void ipc_rx_user_handler(struct ipc_msg_t *msg, uint8_t chn)
{
    uint8_t channel;

    //printf("ipc_rx_user_handler: msg=%d, length=%d\r\n", msg->format, msg->length);

    switch(msg->format) {
        case IPC_MSG_RAW_FRAME:
            mp3_decoder_recv_frame(ipc_get_buffer_offset(IPC_DIR_MCU2DSP, chn), msg->length);
            break;
        case IPC_MSG_WITHOUT_PAYLOAD:
            switch(msg->length) {
                case IPC_SUB_MSG_DECODER_START:
					{
                        struct task_msg_t *msg = task_msg_alloc(MP3_DECODER_INIT, 1);
                        uint8_t *param = (void *)&msg->param[0];
                        *param = 0;
						task_msg_insert(msg);
					}
                    break;
                case IPC_SUB_MSG_NEED_MORE_SBC:
                	{
						struct task_msg_t *msg = task_msg_alloc(MCU_NEED_MORE_SBC_DATA, 0);
						task_msg_insert(msg);
					}
                    break;
                case IPC_SUB_MSG_REINIT_DECODER:
                    break;
                case IPC_SUB_MSG_NREC_START:
                    printf("audio algorithm start\r\n");
                    {
                        struct task_msg_t *msg;
                        msg = task_msg_alloc(AUDIO_ALGO_CREATE, 0);
                        task_msg_insert(msg);
                    }
                    break;
                case IPC_SUB_MSG_NREC_STOP:
                    printf("audio algorithm release\r\n");
                    {
                        struct task_msg_t *msg;
                        msg = task_msg_alloc(AUDIO_ALGO_DESTROY, 0);
                        task_msg_insert(msg);
                    }
                    break;
                case IPC_SUB_MSG_DECODER_PREP_NEXT:
                    {
                        struct task_msg_t *msg;
                        msg = task_msg_alloc(DECODER_PREPARE_FOR_NEXT, 0);
                        task_msg_insert(msg);
                    }
                    break;
                case IPC_SUB_MSG_DECODER_START_LOCAL:
                    {
                        struct task_msg_t *msg = task_msg_alloc(MP3_DECODER_INIT, 1);
                        uint8_t *param = (void *)&msg->param[0];
                        *param = 1;
                        task_msg_insert(msg);
                    }
                    break;
                default:
                    break;
            }
            break;
		case IPC_MSG_FLASH_OPERATION:
			ota_recv_ipc_msg(chn);
			break;
        case IPC_MSG_SET_SBC_CODEC_PARAM:
        	memcpy(&sbc_info,ipc_get_buffer_offset(IPC_DIR_MCU2DSP, chn),sizeof(struct sbc_info_t));
        	break;

        case IPC_MSG_M3_INPUT:   //����MCU IPC��Ϣ
        	//printf("IPC_MSG_M3_INPUT    running\r\n");

            //data=pvPortMalloc(msg->length);
            //*data= ipc_get_buffer_offset(IPC_DIR_MCU2DSP, chn);

     memcpy(MCU_Data,ipc_get_buffer_offset(IPC_DIR_MCU2DSP, chn),msg->length);


            if(MCU_Data[3]==1)
            {
            	Touch_Status.Ispress=true;
            	//printf("touch press\r\n");
            }
            else
            {
            	Touch_Status.Ispress=false;
            	//printf("touch release\r\n");
            }




            Touch_Status.x = MCU_Data[4] & 0x0f;
            Touch_Status.x <<= 8;
            Touch_Status.x += MCU_Data[5];

            Touch_Status.y = MCU_Data[6] & 0x0f;
            Touch_Status.y <<= 8;
            Touch_Status.y += MCU_Data[7];

#if 1
      if(Touch_Status_Stack_Is_Init() ==  1)
      {
	    Touch_Status_Stack_Push(&Touch_Stack,&Touch_Status);
      }
#endif
			

      #if 0
      printf(" Touch_Status.x=%d,Touch_Status.y=%d \r\n", Touch_Status.x,Touch_Status.y);
     #endif

        	//ipc_get_buffer_offset(IPC_DIR_MCU2DSP, chn),msg->length;
   //printf("msg->length=%d\r\n",msg->length);




#if 0
            vPortFree(data);
#endif






        	break;
        default:
            break;
    }
}

void decoder_prepare_for_next_handler(void *arg)
{
    mp3_decoder_destroy();
    ipc_msg_send(IPC_MSG_WITHOUT_PAYLOAD, IPC_SUB_MSG_DECODER_PREP_READY, NULL);
}




void TOUCH_EVENT_handler(void *arg)
{
   printf("TOUCH_EVENT_handler  running\r\n");
}


static struct task_msg_handler_t user_msg_handler[] =
{
    // ����os_timer���û�����ɾ��
    {OS_TIMER_TRIGGER,			os_timer_trigger_handler},

    {TOUCH_EVENT,TOUCH_EVENT_handler},
#if 0
    // �����Ӧ���йأ�����Ķ�������ʾ��
    {MP3_DECODER_INIT,			mp3_decoder_init},
    {MP3_DECODER_DO_DECODE,     mp3_decoder_do_decoder_handler},
    {MCU_NEED_MORE_SBC_DATA,	sbc_encoder_recv_frame_req},
    {AUDIO_IPC_DMA_RX,       	audio_algorithm_ipc_rx_handler},
    {AUDIO_IPC_DMA_TX, 	 		audio_algorithm_ipc_tx_handler},
    {TEST_FLASH_READ_WRITE,     test_flash_read_write},
    {AUDIO_ALGO_CREATE,         audio_init},
    {AUDIO_ALGO_DESTROY,        audio_algorithm_release},
    {RECEIVE_AT_COMMAND,        app_at_cmd_recv_handler},
    {DECODER_PREPARE_FOR_NEXT,  decoder_prepare_for_next_handler},
#endif
    {TASK_ID_DEFAULT,           NULL},
};

__attribute__((section("iram_section"))) void flash_reinit(void)
{
	uint32_t flash_id;
	extern const struct qspi_stig_reg_t read_id_cmd;

	GLOBAL_INT_DISABLE();

	qspi_stig_cmd(read_id_cmd, QSPI_STIG_CMD_READ, 3, (uint8_t *)&flash_id);
	flash_id &= 0xffffff;

	// ��spi controller���ó�4�ߵĶ�
    qspi_flash_init_controller(4, 0);
    // ʹ��flash��4�ߣ�����0��ʾ��0x01 opcode��1��ʾ��0x31 opcode����ͬ��flash���ò�ͬ��opcode����Ҫ��flash��datasheet
    if((flash_id == FLASH_ID_PUYA_64M)
    	|| (flash_id == FLASH_ID_PUYA_32M)
    	|| (flash_id == FLASH_ID_PUYA_128M)
    	|| (flash_id == FLASH_ID_BOYA_128M)
    	|| (flash_id == FLASH_ID_DOSI_64M)
    	|| (flash_id == FLASH_ID_UNKNOWN_128M)
    	|| (flash_id == FLASH_ID_BY_USER)) {

    	printf(" qixin this flash(ID: %08x) to enable quad operation.\r\n", flash_id);


    	qspi_flash_enable_quad(1);
    }
    else if((flash_id == FLASH_ID_XTX_128M)
    	|| (flash_id == FLASH_ID_PUYA_16M)
    	|| (flash_id == FLASH_ID_PUYA_4M)) {
    	qspi_flash_enable_quad(0);
    }
    else if(flash_id == FLASH_ID_NORMEM_64M) {
        qspi_flash_enhance_drive(0x60);
        qspi_flash_enable_quad(2);
    }
    else {
    	printf("WARNING: please confirm opcode used by this flash(ID: %08x) to enable quad operation.\r\n", flash_id);
    	qspi_flash_enable_quad(0);
    }
    // ��д����֮����Զ�poll�����ر�
    qspi_poll_set_disable(1);

    // ����Ƶ�����ó�div2
	/*
	 * QSPI_BAUDRATE_DIV_2  - 3
	 * QSPI_BAUDRATE_DIV_4  - 0
	 */
#if 0
    qspi_ctrl->delay.sel_dessert = 5;
	qspi_ctrl->read_cap.delay_capture = 3;
	qspi_cfg_set_baudrate(QSPI_BAUDRATE_DIV_8);
#endif
#if 1
	qspi_ctrl->read_cap.delay_capture = 3;
	qspi_cfg_set_baudrate(QSPI_BAUDRATE_DIV_2);
#endif
    GLOBAL_INT_RESTORE();
}

__attribute__((section("iram_section"))) void flash_load_data(uint8_t *dst, uint8_t *src, uint32_t length)
{
    GLOBAL_INT_DISABLE();
    while(qspi_is_busy());
    qspi_ctrl->delay.sel_dessert = 5;
    qspi_ctrl->read_cap.delay_capture = 0;

    if((((uint32_t)dst | (uint32_t)src) & 0x03) == 0) {
        qspi_cfg_set_baudrate(QSPI_BAUDRATE_DIV_4);
        uint32_t *ptr_src = (uint32_t *)src;
        uint32_t *ptr_dst = (uint32_t *)dst;
        uint32_t trans_length = length >> 2;

        for(uint32_t i=0; i<trans_length; i++) {
            *ptr_dst++ = *ptr_src++;
        }
        length -= (trans_length << 2);
        dst = (uint8_t *)ptr_dst;
        src = (uint8_t *)ptr_src;
    }
    else {
        qspi_cfg_set_baudrate(QSPI_BAUDRATE_DIV_10);
    }
    for(uint32_t i=0; i<length; i++) {
        *dst++ = *src++;
    }

    while(qspi_is_busy());
    qspi_ctrl->delay.sel_dessert = 5;
    qspi_ctrl->read_cap.delay_capture = 3;
    qspi_cfg_set_baudrate(QSPI_BAUDRATE_DIV_2);
    GLOBAL_INT_RESTORE();
}

__attribute__((weak)) void uart_receive_char(uint8_t c)
{
    uart_putc_noint(c);
}

__attribute__((section("iram_section"))) void test_flash_read(void)
{
#define TEST_FLASH_READ_LENGTH          2048
    uint8_t *buffer;
    printf("test read flash start\r\n");
    buffer = pvPortMalloc(TEST_FLASH_READ_LENGTH);
    uint32_t start_addr = 0x20000000;
    uint32_t end_addr = start_addr + 140*1024;
    for(; start_addr < end_addr; start_addr += TEST_FLASH_READ_LENGTH) {
        flash_load_data(buffer, (void *)start_addr, TEST_FLASH_READ_LENGTH);
        for(uint32_t i=0; i<TEST_FLASH_READ_LENGTH;) {
            printf("%02x", buffer[i]);
            i++;
            if((i % 16) == 0) {
                printf("\r\n");
            }
        }
    }
    flash_load_data(buffer, (void *)0x20000002, TEST_FLASH_READ_LENGTH);
    vPortFree(buffer);
    printf("test read flash end\r\n");
}

// �û��������ں���
void app_entry(void)
{
    uint8_t channel;

    init_memory();

    printf("enter app entry: BUILD DATE: %s, TIME: %s\r\n", __DATE__, __TIME__);
    printf("user main v1.0.4\r\n");

    flash_reinit();

    // ע���û��Լ���IPC���մ��?��
    app_ipc_rx_set_user_handler(ipc_rx_user_handler);
    // ��ʼ���ڲ��Ļ���whileѭ���������б�
    task_init();
    // ��ʼ��os_timer
    os_timer_engine_init();

    uart_init(BAUD_RATE_115200, uart_receive_char);//���ڳ�ʼ��
    _xtos_interrupt_enable(XCHAL_UART_INTERRUPT);

   #include "picure.h"
    st7796h_init();//��ʼ����Ļ
   //st7796h_draw_solid_rect(0,0,240,240,0x0000);

/*
	#define TEST_FLASH_READ_LENGTH			115200
    uint8_t buffer[115200];
    memcpy(buffer, gImage_bg3, 115200);
    printf("gImage_bg3=%x",gImage_bg3);
	st7796h_draw(0, 0, 240, 240, buffer);
	co_delay_100us(5000);
	co_delay_100us(5000);
	co_delay_100us(5000);
	co_delay_100us(5000);
*/


   //LCD_Draw_Image(0,0,0,0,bg1Image_ADDRESS);

#if 0
    LCD_Draw_Image(120,20,0,0,zoom_shutdown_50Image_ADDRESS);
    LCD_Draw_Image(120,70,0,0,zoom_skip_50Image_ADDRESS);
    LCD_Draw_Image(120,120,0,0,zoom_sleep_50Image_ADDRESS);
    LCD_Draw_Image(120,170,0,0,zoom_stopwatch_50Image_ADDRESS);
    LCD_Draw_Image(170,120,0,0,zoom_swim_50Image_ADDRESS);
#endif
	
    printf("LCD Init Success\r\n");
    Time_Init(&my_Time);
	os_timer_init(&My_time_timer, My_time_timer_function, NULL);    //时间定时器
	//os_timer_start(&My_time_timer, 200,  OS_TIMER_TYPE_REPEAT);



    GUI_Touch_Init();   //初始化触摸屏

    printf("\r\n");
    printf("\r\n");
    printf("\r\n");
    printf("\r\n");
    printf("\r\n");
    printf("\r\n");
    printf("\r\n");
    printf("\r\n");
    printf("\r\n");
    printf("GUITouch_Init success\r\n");
#if 1   //My GUI
	os_timer_init(&GUI_timer, GUI_timer_function, NULL);    //显示定时器
	os_timer_start(&GUI_timer, 30,  OS_TIMER_TYPE_REPEAT);

	os_timer_init(&Touch_timer, Touch_timer_function, NULL);//触摸定时器
	os_timer_start(&Touch_timer,30,  OS_TIMER_TYPE_REPEAT);

#endif



	#if 0 //����ˢ���ɹ�

		os_timer_init(&test_st7796_timer, test_st7796_timer_function, NULL);

		os_timer_start(&test_st7796_timer, 500,  OS_TIMER_TYPE_REPEAT);
	#endif







    printf("LCD Init Success Ok\r\n");

#if 0
     //LVGL GUI��س�ʼ��
    /******************************************************************************/
            lv_init();
    		printf("lv_init\r\n");
    		co_delay_100us(20);

    		lv_port_disp_init();
    		lv_port_indev_init();
    		printf("lv_port_disp_init\r\n");

    		printf("LV Success Init\r\n");
    		table_Init();//����
			os_timer_init(&test_lvgl_timer, test_lvgl_timer_function, NULL);
			os_timer_start(&test_lvgl_timer, 10, OS_TIMER_TYPE_REPEAT);

			os_timer_init(&lvgl_tick_timer, lvgl_tick_function, NULL);
			os_timer_start(&lvgl_tick_timer, 5, OS_TIMER_TYPE_REPEAT);

	/********************************************************************************/



      #if 0
    	 LV_IMG_DECLARE(main_back);//����ͼƬ��Դ
   		 LV_IMG_DECLARE(minute);   //����ͼƬ��Դ
   		 LV_IMG_DECLARE(hour);   //����ͼƬ��Դ
   		 LV_IMG_DECLARE(second);   //����ͼƬ��Դ

    		lv_obj_t * img1 = lv_img_create(lv_scr_act(), NULL);
    	    lv_img_set_src(img1, &bg1);
    	    lv_obj_align(img1, NULL, LV_ALIGN_CENTER, 0, 0);


     		img2 = lv_img_create(img1, NULL);
     	    lv_img_set_src(img2, &second);
     	    lv_obj_set_pos(img2, 120, 0);



    		img3 = lv_img_create(img1, NULL);
    	    lv_img_set_src(img3, &minute);
    	    lv_obj_set_pos(img3, 120, 0);


    	    img4 =lv_img_create(img1, NULL);
    	    lv_img_set_src(img4, &hour);
    	    lv_obj_set_pos(img4, 120-10, 28);



    		lv_img_set_pivot(img2, 0, 120);//������ת���
    		lv_img_set_pivot(img3, 0, 120);//������ת���
    		lv_task_create(rolate_Hander, 10, LV_TASK_PRIO_HIGHEST, NULL);
    		//lv_task_create(task4_cb, 5000, LV_TASK_PRIO_MID, NULL);



    		//lv_task_create(task4_cb, 5000, LV_TASK_PRIO_MID, NULL);
    		printf("IMG Init\r\n");
		#endif

#endif



#if 0 //����ˢ���ɹ�

    os_timer_init(&test_st7796_timer, test_st7796_timer_function, NULL);

    os_timer_start(&test_st7796_timer, 500,  OS_TIMER_TYPE_REPEAT);
#endif

#if 0
    os_timer_init(&test_st7789_timer,test_st7796_timer_function,NULL);
    os_timer_start(&test_st7789_timer,20, OS_TIMER_TYPE_REPEAT);

#endif


   // struct os_timer_t test_lvgl_timer;
   // void test_lvgl_timer_function(void *arg)


    //os_timer_init(&test_flash_rw_timer, test_flash_rw_timer_function, NULL);
    //os_timer_start(&test_flash_rw_timer, 10000, OS_TIMER_TYPE_REPEAT);

    //os_timer_init(&test_rm69330_timer, test_rm69330_timer_function, NULL);
    //os_timer_start(&test_rm69330_timer, 10, OS_TIMER_TYPE_REPEAT);
    //os_timer_init(&test_rm69330_button_timer, test_rm69330_button_timer_function, NULL);
    //os_timer_start(&test_rm69330_button_timer, 1000, OS_TIMER_TYPE_REPEAT);

    //os_timer_init(&test_gc9c01_timer, test_gc9c01_timer_function, NULL);
    //os_timer_start(&test_gc9c01_timer, 10, OS_TIMER_TYPE_REPEAT);
    //os_timer_init(&test_gc9c01_button_timer, test_gc9c01_button_timer_function, NULL);
    //os_timer_start(&test_gc9c01_button_timer, 1000, OS_TIMER_TYPE_REPEAT);

    // ����һ���µ���Ϣ�������͵���Ϣ�б�
    //struct task_msg_t *msg = task_msg_alloc(TEST_LCD_RM69330_DISPLAY, 0);
    //task_msg_insert(msg);

//    test_flash_read();

    /* inform MCU that DSP is ready */
    ipc_msg_send(IPC_MSG_WITHOUT_PAYLOAD, IPC_SUM_MSG_DSP_USER_CODE_READY, NULL);

    // ����������ȣ�����ú���󲻻��ٳ�����
    task_schedule(user_msg_handler, sizeof(user_msg_handler)/sizeof(user_msg_handler[0]));
}
